<?php

declare(strict_types=1);
/**
 * This file is part of MoChat.
 * @link     https://mo.chat
 * @document https://mochat.wiki
 * @contact  group@mo.chat
 * @license  https://github.com/mochat-cloud/mochat/blob/master/LICENSE
 */
namespace MoChat\App\WorkContact\Logic;

use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\Codec\Json;
use MoChat\App\Corp\Constants\WorkUpdateTime\Type;
use MoChat\App\Corp\Contract\CorpContract;
use MoChat\App\Corp\Contract\WorkUpdateTimeContract;
use MoChat\App\WorkContact\Constants\Gender;
use MoChat\App\WorkContact\Constants\Room\Type as ContactType;
use MoChat\App\WorkContact\Contract\ContactFieldPivotContract;
use MoChat\App\WorkContact\Contract\WorkContactContract;
use MoChat\App\WorkContact\Contract\WorkContactEmployeeContract;
use MoChat\App\WorkContact\Contract\WorkContactRoomContract;
use MoChat\App\WorkContact\Contract\WorkContactTagContract;
use MoChat\App\WorkContact\Contract\WorkContactTagPivotContract;
use MoChat\App\WorkDepartment\Contract\WorkDepartmentContract;
use MoChat\App\WorkEmployee\Contract\WorkEmployeeContract;
use MoChat\App\WorkEmployee\Contract\WorkEmployeeDepartmentContract;
use MoChat\App\WorkRoom\Contract\WorkRoomContract;
use MoChat\Plugin\ContactFollow\Contract\ContactFollowContract;
use MoChat\Plugin\ContactStage\Contract\ContactStageContract;
use MoChat\Plugin\ContactTrack\Contract\ContactTrackContract;

/**
 * 客户列表.
 *
 * Class IndexLogic
 */
class IndexTrackLogic
{
    /**
     * @Inject
     * @var WorkEmployeeDepartmentContract
     */
    protected $workEmployeeDepartmentService;

    /**
     * @Inject
     * @var WorkDepartmentContract
     */
    protected $workDepartmentService;

    /**
     * @Inject
     * @var ContactStageContract
     */
    protected $contactStageService;

    /**
     * @Inject
     * @var WorkContactTagPivotContract
     */
    protected $workContactTagPivotService;

    /**
     * @Inject
     * @var ContactTrackContract
     */
    protected $contactTrackService;

    /**
     * @Inject
     * @var ContactFollowContract
     */
    protected $contactFollowService;

    /**
     * 客户表.
     * @Inject
     * @var WorkContactContract
     */
    private $contact;

    /**
     * 员工 - 客户关联.
     * @Inject
     * @var WorkContactEmployeeContract
     */
    private $contactEmployee;

    /**
     * 标签.
     * @Inject
     * @var WorkContactTagContract
     */
    private $contactTag;

    /**
     * 客户 - 标签关联.
     * @Inject
     * @var WorkContactTagPivotContract
     */
    private $contactTagPivot;

    /**
     * 用户画像.
     * @Inject
     * @var ContactFieldPivotContract
     */
    private $contactFieldPivot;

    /**
     * 客户群.
     * @Inject
     * @var WorkRoomContract
     */
    private $room;

    /**
     * 客户 - 群关联.
     * @Inject
     * @var WorkContactRoomContract
     */
    private $contactRoom;

    /**
     * 同步时间.
     * @Inject
     * @var WorkUpdateTimeContract
     */
    private $workUpdateTime;

    /**
     * 员工.
     * @Inject
     * @var WorkEmployeeContract
     */
    private $employee;

    /**
     * 企业表.
     * @Inject
     * @var CorpContract
     */
    private $corp;

    /**
     * 参数.
     * @var array
     */
    private $params;

    /**
     * @return array
     */
    public function handle(array $params)
    {
        $params['corpId'] = user()['corpIds'][0];
        // 处理查询
        if (empty($params['templateId'])) {
            $track = $this->contactTrackService->getContactTrackBySearch($params, ['id', 'employee_id', 'contact_id', 'event', 'content', 'created_at']);
        } else {
            $where['corp_id'] = user()['corpIds'][0];
            $where['follow_template_id'] = $params['templateId'];
            if (! empty($params['startTime'])) {
                $where[] = ['created_at', '>=', $params['startTime']];
            }
            if (! empty($params['endTime'])) {
                $where[] = ['created_at', '<=', $params['endTime']];
            }
            $options = [
                'page' => $params['page'],
                'perPage' => $params['perPage'],
                'orderByRaw' => 'id desc',
            ];
            $track = $this->contactFollowService->getContactFollowList($where, ['id', 'employee_id', 'contact_id', 'content', 'created_at'], $options);
        }

        // 标明没有数据
        if (empty($track)) {
            return [
                'page' => [
                    'perPage' => 20,
                    'total' => 0,
                    'totalPage' => 0,
                ],
                'list' => [],
                'syncContactTime' => '',
            ];
        }

        // 获取客户列表
        return $this->getContactEmployeeInfo($track);
    }

    /**
     * 获取客户列表.
     * @return array
     */
    private function getContactEmployeeInfo(array $track)
    {
        $contactIds = array_unique(array_column($track['data'], 'contactId'));
        $columns = [
            'id',
            'employee_id',
            'contact_id',
            'remark',
            'create_time',
            'add_way',
            'last_message_time',
        ];

        // 查询数据
        $info = $this->contactEmployee->getWorkContactEmployeesByContactIds($contactIds, $columns);

        if (empty($info)) {
            return [];
        }
        $contactEmployee = [];
        foreach ($info as $v) {
            $contactEmployee[$v['contactId'] . '-' . $v['employeeId']] = $v;
        }
        // 员工id
        $employeeIds = array_unique(array_column($track['data'], 'employeeId'));
        // 查询客户基础信息
        $contact = $this->getContactInfo($contactIds);
        // 查询客户归属成员信息
        $employee = $this->getEmployee($employeeIds);
        // 查询客服所属部门
        $department = $this->getEmployeeDepartment($employeeIds);

        foreach ($track['data'] as &$raw) {
            $raw['createTime'] = $contactEmployee[$raw['contactId'] . '-' . $raw['employeeId']]['createTime'] ?? '';
            if (str_starts_with($raw['content'], '{')) {
                $raw['content'] = Json::decode($raw['content']);
            } else {
                $raw['content'] = [
                    'title' => '',
                    'content' => $raw['content'],
                ];
            }
            $raw['genderText'] = '';
            $raw['businessNo'] = '';
            $raw['name'] = '';
            $raw['avatar'] = '';
            if (isset($contact[$raw['contactId']])) {
                $raw['businessNo'] = $contact[$raw['contactId']]['businessNo'];
                $raw['name'] = $contact[$raw['contactId']]['name'];
                $raw['avatar'] = $contact[$raw['contactId']]['avatar'] ? file_full_url($contact[$raw['contactId']]['avatar']) : $contact[$raw['contactId']]['avatar'];
                $raw['gender'] = $contact[$raw['contactId']]['gender'];
                $raw['genderText'] = Gender::getMessage($contact[$raw['contactId']]['gender']);
            }

            $raw['remark'] = $contactEmployee[$raw['contactId'] . '-' . $raw['employeeId']]['remark'] ?? '';

            $raw['employeeName'] = [];
            if (isset($employee[$raw['employeeId']])) {
                $raw['employeeName'] = $employee[$raw['employeeId']]['name'];
            }
            // 客服部门
            $raw['departmentName'] = empty($department[$raw['employeeId']]) ? [] : array_unique($department[$raw['employeeId']]);

            // 查询客户标签
            $raw['tag'] = $this->getContactTag($raw['contactId'], $raw['employeeId']);
        }
        unset($raw);

        // 返回数据
        $data = [
            'page' => [
                'perPage' => $track['per_page'] ?? 20,
                'total' => $track['total'] ?? 0,
                'totalPage' => $track['last_page'] ?? 0,
            ],
            'list' => empty($track['data']) ? [] : $track['data'],
        ];

        return $data;
    }

    private function getEmployeeDepartment($employeeIds): array
    {
        // 客服部门
        $department = $this->workEmployeeDepartmentService->getWorkEmployeeDepartmentsByEmployeeIds($employeeIds, ['employee_id', 'department_id']);
        if (empty($department)) {
            return [];
        }
        $departmentIds = array_column($department, 'departmentId');
        // 部门信息
        $departmentNames = $this->workDepartmentService->getWorkDepartmentsById($departmentIds, ['id', 'name']);
        if (empty($departmentNames)) {
            return [];
        }
        $departmentName = [];
        foreach ($departmentNames as $name) {
            $departmentName[$name['id']] = $name['name'];
        }
        // 客服部门名称
        $employeeDepartment = [];
        foreach ($department as $item) {
            $employeeDepartment[$item['employeeId']][] = $departmentName[$item['departmentId']];
        }
        return $employeeDepartment;
    }

    /**
     * 获取客户信息.
     * @param $contactIds
     * @return array
     */
    private function getContactInfo($contactIds)
    {
        $contact = $this->contact->getWorkContactsById($contactIds);
        if (! empty($contact)) {
            $contact = array_column($contact, null, 'id');
        }

        return $contact;
    }

    /**
     * 查询员工信息.
     * @param $employeeIds
     * @return array
     */
    private function getEmployee($employeeIds)
    {
        // 根据员工id查询员工信息、企业id
        $employeeInfo = $this->employee->getWorkEmployeesById($employeeIds, ['id', 'name', 'corp_id']);

        if (empty($employeeInfo)) {
            return [];
        }

        $corpIds = array_unique(array_column($employeeInfo, 'corpId'));

        // 查询企业名称
        $corpInfo = $this->corp->getCorpsById($corpIds, ['id', 'name']);
        if (empty($corpInfo)) {
            return [];
        }
        $corpInfo = array_column($corpInfo, null, 'id');

        foreach ($employeeInfo as &$raw) {
            $raw['corpName'] = '';

            if (isset($corpInfo[$raw['corpId']])) {
                $raw['corpName'] = $corpInfo[$raw['corpId']]['name'];
            }
        }

        unset($raw);

        $employeeInfo = array_column($employeeInfo, null, 'id');

        return $employeeInfo;
    }

    /**
     * 获取客户标签.
     * @param $contactId
     * @param $employeeId
     * @return array
     */
    private function getContactTag($contactId, $employeeId)
    {
        $contactTag = $this->contactTagPivot->getWorkContactTagPivotsByOtherId($contactId, $employeeId);
        if (empty($contactTag)) {
            return [];
        }

        $tagIds = array_unique(array_column($contactTag, 'contactTagId'));
        // 根据标签id查询标签名称
        $tagInfo = $this->contactTag->getWorkContactTagsById($tagIds, ['id', 'name']);

        if (empty($tagInfo)) {
            return [];
        }

        $tagInfo = array_column($tagInfo, null, 'id');

        $tagName = [];
        foreach ($contactTag as &$raw) {
            if (isset($tagInfo[$raw['contactTagId']])) {
                $tagName[] = $tagInfo[$raw['contactTagId']]['name'];
            }
        }
        unset($raw);

        $tagName = array_unique($tagName);

        return $tagName;
    }

    /**
     * 获取客户所在群.
     * @param $contactIds
     * @return array
     */
    private function getContactRoom($contactIds)
    {
        $contactRoom = $this->contactRoom->getWorkContactRoomsByContactIdsType($contactIds, (int) ContactType::CONTACT, ['contact_id', 'room_id']);
        if (empty($contactRoom)) {
            return [];
        }

        $roomIds = array_column($contactRoom, 'roomId');
        // 根据群id查询群名称
        $roomInfo = $this->room->getWorkRoomsById($roomIds, ['id', 'name']);

        if (! empty($roomInfo)) {
            $roomInfo = array_column($roomInfo, null, 'id');
        }

        $contactData = [];
        foreach ($contactRoom as &$raw) {
            $raw['roomName'] = '';
            if (isset($roomInfo[$raw['roomId']])) {
                $raw['roomName'] = $roomInfo[$raw['roomId']]['name'];
            }

            if (isset($contactData[$raw['contactId']])) {
                $contactData[$raw['contactId']]['roomName'][] = $raw['roomName'];
            } else {
                $tmp = [];
                $tmp['roomName'][] = $raw['roomName'];

                $contactData[$raw['contactId']] = $tmp;
            }
        }

        unset($raw);

        return $contactData;
    }

    /**
     * 获取最后一次同步客户的时间.
     * @return mixed
     */
    private function getTime()
    {
        $type = Type::CONTACT;

        $res = $this->workUpdateTime->getWorkUpdateTimeByCorpIdType(user()['corpIds'], (int) $type, ['last_update_time']);

        return empty($res) ? '' : end($res)['lastUpdateTime'];
    }
}
